package org.hs.im.forensicj.view.imageviewer;

import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.RenderedImage;
import java.util.ArrayList;
import java.util.List;

import org.hs.im.forensicj.view.ImageViewer;
import org.hs.im.forensicj.view.ImageViewer.MouseMode;
import org.hs.im.forensicj.view.ImageViewerListener;

import com.sun.media.jai.widget.DisplayJAI;

public class DefaultImageViewer extends DisplayJAI implements ImageViewer {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private MouseMode mouseMode;

	private int mouseClicX;

	private int mouseClicY;
	
	private AffineTransform transform;

	private RenderedImage image;

	private List<ImageViewerListener> listeners;
	

	
	
	public DefaultImageViewer(RenderedImage image) {
		super(image);
		setImage(image);
		this.listeners = new ArrayList<ImageViewerListener>();
		transform = new AffineTransform();
		setNormalMouseMode();
		addMouseListener(this);
		addMouseMotionListener(this);

	}
	
	
	@Override
	public void mousePressed(MouseEvent evt) {
		mouseClicX = evt.getX();
		mouseClicY = evt.getY();
	}
	
	@Override
	public void mouseClicked(MouseEvent evt) {
		if(mouseMode == MouseMode.ZOOM_IN){
			double zoomLevel = getZoomLevel()*2;
			if ( zoomLevel <= 32 ){
				setZoomLevel(zoomLevel);
			}
		}else if(mouseMode == MouseMode.ZOOM_OUT){
			double zoomLevel = getZoomLevel()/2;
			if ( zoomLevel >= 1.0/16 ){
				setZoomLevel(zoomLevel);
			}
		}
	}
	
	
	@Override
	public synchronized void paintComponent(Graphics g) {
		Graphics2D g2 = (Graphics2D) g;
		
		g2.drawRenderedImage(image, transform);
	}
	

	@Override
	public void setNormalMouseMode() {
		mouseMode = MouseMode.NORMAL;
		setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
	}

	@Override
	public void setSelectionMouseMode() {
		mouseMode = MouseMode.SELECTION;
		setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
	}

	@Override
	public void setPanMouseMode() {
		mouseMode = MouseMode.PAN;
		setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
	}

	@Override
	public void setZoomInMouseMode() {
		mouseMode = MouseMode.ZOOM_IN;
		setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
	}

	@Override
	public void setZoomOutMouseMode() {
		mouseMode = MouseMode.ZOOM_OUT;
		setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
	}

	@Override
	public void setZoomToRegionMouseMode() {
		mouseMode = MouseMode.ZOOM_TO_REGION;
		setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
	}

	@Override
	public void zoomToActualImageResolution() {
		setZoomLevel(1);
	}

	@Override
	public void zoomToFitToWindow() {
		Dimension size = getSize();
		double zoomLevel = Math.min( size.getWidth()/image.getWidth(), size.getHeight()/image.getHeight() );
		setZoomLevel(zoomLevel);
	}

	@Override
	public void zoomToFillToWindow() {
		Dimension size = getSize();
		double zoomLevel = Math.max( size.getWidth()/image.getWidth(), size.getHeight()/image.getHeight() );
		setZoomLevel(zoomLevel);
	}


	@Override
	public Component getComponent() {
		return this;
	}


	@Override
	public double getZoomLevel() {
		return transform.getScaleX();
	}


	@Override
	public void setZoomLevel(double zoomLevel) {
		transform.setTransform(
				zoomLevel, transform.getShearY(), transform.getShearX(), 
				zoomLevel, transform.getTranslateX(), transform.getTranslateY());
		repaint();
		
		for (ImageViewerListener listener : listeners) {
			listener.zoomChanged(zoomLevel);
		}
	}

	@Override
	public void rotateLeft() {
		transform.rotate(Math.PI/2);
		
		repaint();
	}

	@Override
	public void rotateRight() {
		transform.rotate(-Math.PI/2);
		repaint();
	}

	@Override
	public void flipVertical() {
		transform.shear(1, -1);
		repaint();
	}

	@Override
	public void flipHorizontal() {
		transform.shear(-1, 1);
		repaint();
	}

	@Override
	public void addImageViewerListener(ImageViewerListener imageViewerListener) {
		listeners.add(imageViewerListener);
	}

	@Override
	public void copyToClipboard() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void cutToClipboard() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void pasteFromClipboard() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void undo() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void redo() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void cropToSelection() {
		// TODO Auto-generated method stub
		
	}


	@Override
	public RenderedImage getImage() {
		return image;
	}


	@Override
	public void setImage(RenderedImage image) {
		this.image = image;
		repaint();
	}



}
